home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-15 | 70.7 KB | 1,680 lines |
- RDCF: A Reentrant DOS-Compatible File System, Version 2.0
-
- by Philip J. Erdelsky
- PLAIN VANILLA CORPORATION
- CompuServe 75746,3411
- InterNet 75746.3411@compuserve.com
-
- January 15, 1993
-
- Copyright (c) 1993 Plain Vanilla Corporation
-
-
-
- 1. Introduction
- ---------------
-
- RDCF is a reentrant and ROMable DOS-compatible file system designed for use
- with floppy diskettes and hard disk partitions that do not exceed 32 Mbytes in
- size.
-
- For users who are familiar with version 1.0, here is a summary of the
- differences between versions 1.0 and 2.0:
-
- (1) Version 2.0 supports subdirectories and volume names. This is by far
- the most important difference.
-
- (2) Version 2.0 can be compiled to adapt to different sector sizes at run
- time.
-
- (3) Version 2.0 has no default drive option, but it can be compiled with or
- without multiple drive support.
-
- (4) The parameters to some functions have been changed slightly to make them
- more uniform.
-
- (5) Version 2.0 requires access to the system clock, although a dummy access
- function will suffice for systems without clocks.
-
- (6) In version 2.0, the drive access function pointer is stored in the file
- control block by the calling program, instead of being passed as a
- parameter.
-
- (7) In version 2.0, direct access to the file control block is not encouraged
- to the extent it was in version 1.0.
-
- (8) Version 2.0 has a few additional features, such as a directory sort
- function, that were not in version 1.0 and are not in most
- implementations of DOS.
-
- (9) Version 2.0 is copyrighted. Although you may use it non-commercially
- without registering it or paying any fees, resale or commercial use
- requires permission and payment of a one-time royalty.
-
- Although DOS 3 permits characters from the IBM extended character set in file
- names, most DOS applications don't, and neither does RDCF.
-
- Since DOS 1 is now obsolete, RDCF does not support DOS 1 diskette formats.
-
- RDCF is fully reentrant with respect to files on different drives. It is also
- reentrant with respect to files on the same drive, provided they are opened for
- reading only. It is not reentrant with respect to different files on the same
- drive, if any of them are being written. Therefore, access to it in this case
- must be serialized on a drive-by-drive basis when it is used in a multitasking
- system.
-
- RDCF does not call on the memory allocator. All working storage for an open
- file is contained in a file control block and a scratch buffer that you must
- allocate in some manner before calling on RDCF. In a manner of speaking, this
- is a reversion to the old CP/M standard, but it permits complete reentrancy
- and does not limit the number of open files.
-
- Since RDCF treats each open file as though it were the only open file, it
- cannot detect collisions. For example, in a multitasking system, if a file is
- written by two tasks at the same time, it will be corrupted. The disk may end
- up with lost clusters and cross-linked chains, but other files on the same disk
- should keep their integrity.
-
- RDCF requires access to a real-time clock. If your system does not have a
- real-time clock, you can write a dummy clock interface that always returns some
- standard date and time, such as the notorious 1/1/80 00:00:00, which will be
- applied whenever a file is created or modified.
-
- RDCF accesses a disk one sector at a time. While this may seem appallingly
- inefficient, it appears adequate in some cases where only minimal file
- operations are required. A simple cache system, which is also available from
- the same source, will improve its efficiency in other cases. With simple
- interfaces and full source code, you can make other changes that you deem
- necessary for your own application.
-
- RDCF can be compiled as a read-only file system. This eliminates much of the
- code and is suitable for devices that load operating code and other data from
- DOS diskettes but do not write anything on them.
-
- RDCF can be compiled to handle multiple drives, in which case every file
- specification must begin with a drive letter (followed by a colon). If your
- system has only one drive, or if you prefer to handle drive selection outside
- RDCF, you can compile RDCF without multiple drives, in which case a file
- specification must NOT begin with a drive letter.
-
- The interface to RDCF is not ANSI-compliant, although you could put an ANSI
- compliant interface on top of it.
-
-
- 2. Compilation Instructions
- ---------------------------
-
- The source code for RDCF 2.0 consists of the files RDCF2.C and RDCF2.H. The
- header file RDCF2.H should be #included in any source file that calls on the
- RDCF, because it contains function prototypes and other necessary definitions.
-
- Since a DOS diskette contains a number of fields of specific sizes, your C
- compiler must have types of the same sizes. Here is what is required:
-
- type number of bits
- ----- --------------
- char 8
- short 16
- long 32
- int at least 16
-
- If your application is to run on a CPU with "big endian" byte ordering, such as
- one of the Motorola 68000 series, RDCF will have to do some byte swapping
- because DOS diskettes contain fields with "little endian" ordering. You can do
- this by #defining the variable _BIG_ENDIAN.
-
- If you do not need to write anything on disk, you can save a great deal of code
- by #defining the variable RDCF_SYSTEM_READ_ONLY. This eliminates almost all
- code devoted to writing.
-
- If you system has multiple drives, you can #define the variable
- RDCF_MULTIPLE_DRIVES. In this case RDCF will require each file specification
- to begin with a drive letter (followed by a colon), and it will pass the drive
- number to the drive interface.
-
- If your application has only one drive, or if it has more than one drive but
- you want to handle drive selection outside RDCF, leave the variable
- RDCF_MULTIPLE_DRIVES undefined. In this case a file specification passed to
- RDCF must NOT begin with a drive letter.
-
- All DOS diskettes (and nearly all DOS hard disks) use 512-byte sectors, so the
- following definition is included in the header file RDCF2.H:
-
- #define RDCF_SECTOR_SIZE 512
-
- If you change this value, RDCF won't be compatible with DOS, but it can operate
- in a consistent manner on disks that it has formatted.
-
- If you leave RDCF_SECTOR_SIZE undefined, then RDCF will read the sector size
- from the bootstrap sector of each disk. This produces less efficient code,
- because expressions involving the sector size cannot be evaluated at compile
- time. However, it enables RDCF to adapt itself to different sector sizes at
- run time.
-
- You can cut out the code for any RDCF function that you don't need. The
- publicly defined functions in RDCF2.C do not call each other, so one or more
- may be removed without difficulty. For example, if you do only sequential file
- access, you can cut out the function rdcf_seek(). In fact, RDCF probably has
- more functions than most applications require.
-
- RDCF calls on the following standard C functions and macros, which are widely
- available and are usually reentrant:
-
- isalpha() longjmp() memcmp() memcpy() memset() setjmp() toupper()
-
- RDCF presumes that all file specifications are expressed in ASCII and that the
- C compiler uses ASCII for characters and strings.
-
- To prevent identifier conflicts, all publicly defined RDCF labels begin with
- the characters "RDCF", "_RDCF" or "rdcf".
-
- The following public domain packages are usually distributed along with RDCF
- 2.0:
-
- package files
- --------- -----------------------------
- CACHE 1.1 CACHE.C, CACHE.DOC, CACHE.H
- FILES FILES.C, FILES.COM, FILES.DOC
-
- The FILES package contains examples of the use of RDCF. It is also a rather
- handy diskette utility.
-
-
- 3. Drive Access
- ---------------
-
- RDCF does not read or write disks directly. You must supply it with a pointer
- to a function that you have written or adapted for this purpose. RDCF then
- calls this function whenever it needs to read or write a disk sector. The
- format of the function call is as follows:
-
- e = (*drive_access)(write, drive, LSN, buffer);
-
- int write; nonzero (true) for a write operation; zero (false)
- for a read operation
-
- unsigned drive; drive (0=A, 1=B, etc)
-
- unsigned LSN; logical sector number
-
- void *buffer; memory buffer for data
-
- unsigned e; 0 for a successful read or write, or an
- implementation-defined nonzero error code
-
- The function is called to read or write only one sector at a time. However,
- you may want to implement some kind of read-ahead, caching or delayed writing
- at a lower level to improve efficiency.
-
- The function may be required to convert the LSN into side, track and sector
- numbers, although many disk controllers will make the conversion internally.
- The layout of LSN's is fairly standard, and is designed to minimize head
- motion when LSN's are accessed in ascending numerical order. On DOS systems,
- the conversion is made as follows:
-
- sector number = LSN % (number of sectors per track) + 1
-
- side number = (LSN / (number of sectors per track)) % (number of sides)
-
- track number = LSN / ((number of sectors per track) * (number of sides))
-
- The sector size, the number of sectors per track and the number of sides are
- written into the following bytes of LSN 0 (where byte 0 is the first byte):
-
- byte contents
- ---- --------------------------------------
- 11 LS byte of number of bytes per sector
- 12 MS byte of number of bytes per sector
- 24 LS byte of number of sectors per track
- 25 MS byte of number of sectors per track
- 26 LS byte of number of sides
- 27 MS byte of number of sides
-
- If RDCF is to adapt automatically to diskettes of different formats in the same
- drive, the function (*drive_access)() can simply record these values whenever
- LSN 0 is read or written and then use them to find other sectors. Notice that
- LSN 0 is always sector 1 of track 0 on side 0.
-
- An error code must be a 16-bit nonzero unsigned value. Its format is
- implementation-dependent. When RDCF receives a nonzero return value from the
- function (*drive_access)(), it aborts the current operation, puts the return
- value into the file control block member called "drive_error" and returns the
- error code RDCF_DRIVE_ERROR.
-
- Error correction and retries, if any, must be implemented at a lower level.
-
- If RDCF is used in a reentrant fashion, the function (*drive_access)() must
- also have the required reentrancy.
-
- Here is a drive access function that can be used with Turbo C 2.0 (or a
- compatible later version of Borland or Turbo C++) under DOS:
-
- #include <dos.h>
-
- unsigned drive_access(int write, unsigned drive, unsigned LSN,
- void *buffer)
- {
- _SI; _DI;
- return write ? abswrite(drive, 1, LSN, buffer) :
- absread(drive, 1, LSN, buffer);
- }
-
- The strange-looking first line of the function goads the compiler into saving
- and restoring the SI and DI registers, something that absread() and abswrite()
- should do but don't always do, especially when a drive error is detected.
-
- DOS does a little bit of caching when you access disks in this manner.
- Therefore, you should call bdos(13,0,0) to flush the buffers before returning
- control to DOS. Otherwise DOS may not recognize the changes RDCF has made.
-
-
- 4. Real Time Clock Access
- -------------------------
-
- When RDCF needs the date and time, it calls a function as follows:
-
- rdcf_get_date_and_time(p);
-
- struct rdcf_date_and_time *p; pointer to structure to receive
- date and time
-
- You must write a version of rdcf_date_and_time() for your own system. If your
- system has no real-time clock, the following function will supply the notorious
- 1-1-80 00:00:00 as the current date and time:
-
- struct rdcf_date_and_time(struct rdcf_date_and_time *p)
- {
- static struct rdcf_date_and_time DT = {0,0,0,1,1,1980};
- memcpy(p, &DT, sizeof(DT));
- }
-
- If you run RDCF under DOS and use Turbo C 2.0 (or a compatible later version of
- Turbo or Borland C++), the following function will supply the date and time
- taken from the system clock:
-
- void rdcf_get_date_and_time(struct rdcf_date_and_time *p)
- {
- struct date d;
- struct time t;
- int day;
- getdate(&d);
- day = d.da_day;
- gettime(&t);
- getdate(&d);
- if (day != d.da_day) gettime(&t);
- p->month = d.da_mon;
- p->day = d.da_day;
- p->year = d.da_year;
- p->hour = t.ti_hour;
- p->minute = t.ti_min;
- p->second = t.ti_sec;
- }
-
- Notice that it is sometimes necessary to read the date and time twice to be
- sure of getting a consistent reading when the function is called at midnight.
-
- DOS files always have dates in the period 1980-2107.
-
-
- 5. The File Control Block
- -------------------------
-
- All working storage for an open file is contained in a file control block of
- type "struct rdcf", which is defined in the header file RDCF2.H, and a scratch
- buffer described below. You must allocate space for file control blocks and
- scratch buffers before calling on RDCF, since RDCF itself does not call on the
- memory allocator.
-
- The first element of a file control block is a pointer to a scratch buffer
- with room for RDCF_SECTOR_SIZE unsigned characters. The second element is a
- pointer to the drive access function defined above. You must initialize these
- pointers, perhaps as follows:
-
- static unsigned char my_buffer[RDCF_SECTOR_SIZE];
- static struct rdcf f = {my_buffer, drive_access};
-
- If your implementation has a memory allocator, you can use that instead:
-
- struct rcdf f;
- f.buffer = malloc(RDCF_SECTOR_SIZE);
- f.drive_access = drive_access;
-
- If you leave RDCF_SECTOR_SIZE undefined because your system uses different
- sector sizes on different disks, the buffer must be large enough to hold the
- largest sector.
-
- If RDCF_MULTIPLE_DRIVES is undefined, but your system has more than one drive,
- you must also put the appropriate drive number into the member f.drive so that
- it can be passed to the drive access function.
-
- With one exception involving the function rdcf_next_file_information(), neither
- the scratch buffer contents nor the scratch buffer pointer needs to be
- maintained from one call on RDCF to the next. However, if RDCF is to be used
- in a multitasking system, tasks that can call RDCF in a reentrant fashion must
- use different scratch buffers. In most cases, it is sufficient to allocate one
- scratch buffer for each drive, and to serialize calls on RDCF for each drive.
-
- The drive access function pointer must not be changed while the file
- corresponding to the file control block is open.
-
- You don't have to perform any other initialization on your file control
- blocks; RDCF does that for you.
-
- The file control block for a successfully opened file contains a number of
- members that you can (safely) read and/or write directly, without calling on
- RDCF:
-
- member permitted
- access meaning
- --------------- ---------- ----------------------------------------
- buffer read/write pointer to scratch buffer
- drive_access read/write pointer to drive access function
- drive read/write drive (0=A, 1=B, etc.)
- file read file information block, described below
- position read file pointer
- drive_error read error when RDCF_DRIVE_ERROR is returned
- result read result returned by most recent operation
-
- Of course, you should write into the "drive" member only if you have left
- RDCF_MULTIPLE_DRIVES undefined but your system has more than one drive.
-
- The file information block is described more fully in Section 6 below.
-
- File control blocks of the same format are also used by some RDCF functions for
- working storage, although nothing more than result codes are returned in them.
-
-
- 6. The File Information Block
- -----------------------------
-
- The "file" member of a file control block, when filled by RDCF, contains the
- following information about a file:
-
- member meaning
- --------- ---------------------------------------------------
- spec[13] name and extension in ASCII, terminated by \0
- attribute DOS file attribute byte (see below)
- date_and_time file date and time
- first_cluster number of first cluster
- size file length in bytes (0 for volume or subdirectory)
-
- The name and extension are at most eight and three characters long,
- respectively, they are separated by a period (.) if the extension is
- non-blank, and they are terminated by a nul (\0). RDCF always converts small
- letters in file names and extensions to the corresponding capital letters
- before putting them into the file information block.
-
- If the information block represents a volume name, however, then the spec[]
- member contains the name, which is eleven characters long and may contain
- small letters and special characters.
-
- The date_and_time member is itself a structure with the following members:
-
- member meaning range
- ------ --------- -----------------
- second file time 0-58, always even
- minute file time 0-59
- hour file time 0-23
- day file date 1-31
- month file date 1-12
- year file date 1980-2107
-
- The bits of the attribute byte are represented by mnemonics defined in RDCF2.H:
-
- #define RDCF_READ_ONLY 0x01
- #define RDCF_HIDDEN 0x02
- #define RDCF_SYSTEM 0x04
- #define RDCF_VOLUME 0x08
- #define RDCF_DIRECTORY 0x10
- #define RDCF_ARCHIVE 0x20
-
- The file information and date-and-time blocks also appear outside the file
- control block in some contexts.
-
-
- 7. RDCF File Specifications
- ---------------------------
-
- A file specification under RDCF is almost the same as its DOS counterpart.
-
- As in DOS, case is not significant in file specifications. Moreover, every
- name is truncated to eight characters, and every extension is truncated to
- three characters. Hence "A:MYPROGRAM.PASCAL", "A:MYPROGRA.PAS", and
- "a:myprogra.pas" all represent the same file.
-
- In a multiple-drive system, the file specification MUST begin with a drive
- specification (a drive letter followed by a colon). In systems with only one
- drive, the file specification must NOT begin with a drive letter. If you want
- to handle drive selection outside RDCF, adjust the drive access pointer and
- the drive number in the file control block to select the desired drive, and
- then remove the drive letter and colon from the file specification before
- calling on RDCF.
-
- Since there is no "current directory", the file specification must begin at the
- root and contain the names of all intermediate subdirectories. The backslash
- at the beginning of the directory path is superfluous and is NOT used. Hence
- a file specification such as "C:\UTIL\CHKDSK.COM", which is quite familiar
- under DOS, is invalid under RDCF. The RDCF specification is
- "C:UTIL\CHKDSK.COM".
-
- For the same reason, RDCF does not permit the special subdirectories "." and
- ".." in a directory path, but to maintain disk-level compatibility with DOS, it
- puts them into subdirectories that it creates.
-
- A directory specification is the same as a file specification, except that it
- refers to a subdirectory.
-
- Where required, a root directory is represented by a drive specification alone;
- e.g., "B:" represents the root directory on drive B:. In single-drive systems,
- the empty string "" represents the root directory.
-
- RDCF treats all file and drive specifications supplied to it as read-only
- strings. They may reside in ROM.
-
-
- 8. The Program Interface
- ------------------------
-
- The RDCF program interface consists of the following functions:
-
- function description
- --------------------------- -------------------------------------
- rdcf_attribute() change a file attribute
- rdcf_close() close a file
- rdcf_date_and_time() change a file, volume or subdirectory
- date and time
- rdcf_delete() delete a file, volume name or
- subdirectory
- rdcf_directory() create a subdirectory
- rdcf_format() format a disk
- rdcf_free_space() get disk free space
- rdcf_get_file_information() get a directory entry
- rdcf_get_volume() get volume name
- rdcf_match() match name and extension
- rdcf_move() move a file or subdirectory
- rdcf_next_file_information() get next directory entry
- rdcf_open() open a file
- rdcf_read() read from a file
- rdcf_recover() recover erased data
- rdcf_rename() rename a file or directory
- rdcf_seek() move a file pointer
- rdcf_set_file_information() write into a directory entry
- rdcf_set_volume() write volume name
- rdcf_sort_directory() sort a directory
- rdcf_undelete() restore a deleted file
- rdcf_wipe_drive() wipe out erased data
- rdcf_write() write into a file
-
- There are also four externally defined variables, which for reentrancy must be
- considered read-only:
-
- rdcf_format_360 rdcf_format_1200
- rdcf_format_720 rdcf_format_1440
-
-
- 8.1. rdcf_attribute() - Change a File Attribute
- -----------------------------------------------
-
- The following function call changes a file's attribute byte:
-
- e = rdcf_attribute(fcb, filespec, attribute);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; file specification string, with
- terminating \0
-
- unsigned attribute; new attribute byte
-
- int e; 0 if file was successfully modified,
- or negative error code
-
- Only the following attribute bits are affected by this function:
-
- RDCF_ARCHIVE RDCF_READ_ONLY
- RDCF_HIDDEN RDCF_SYSTEM
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- -------------------------------------
- 0 successful operation
- RDCF_DIRECTORY_CONFLICT file name conflicts with subdirectory
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_FORMAT_ERROR corrupt file allocation table
- RDCF_FILE_NOT_FOUND file not found
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.2. rdcf_close() - Close a File
- --------------------------------
-
- If a file has been written or otherwise modified, you must close it in order to
- update its directory entry. Here is the appropriate function call:
-
- e = rdcf_close(fcb);
-
- struct rdcf *fcb; pointer to open file control block
-
- int e; 0 for a successful operation, or a negative error
- code
-
- The file control block must have been successfully opened by rdcf_open().
-
- If the file has been modified, its date and time will be set to the value
- returned by rdcf_get_date_and_time().
-
- If a file has not been written or otherwise modified, there is no need to close
- it, and this function will do nothing to it. If RDCF is compiled as a read-only
- file system, this function is not even defined.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------- --------------------------------
- 0 successful operation
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
-
-
- 8.3. rdcf_date_and_time() - Change Date and Time
- ------------------------------------------------
-
- The following function call changes the date and time of a file, volume name
- or subdirectory:
-
- e = rdcf_date_and_time(fcb, filespec, t);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; file specification string, with
- terminating \0
-
- struct rdcf_date_and_time *t; pointer to block containing desired
- date and time
-
- int e; 0 if operation was successful,
- or negative error code
-
- If RDCF_MULTIPLE_DRIVE is defined, the file specification for a volume name
- consists of a drive specification alone, e.g., "A:" for drive A:, "B:" for
- drive B:, etc. In other cases, the file specification for a volume name is
- the empty string ("").
-
- When the time and date of a subdirectory are changed, the time and date of its
- special subdirectories "." and ".." are also changed.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ----------------------------------
- 0 successful operation
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_FORMAT_ERROR corrupt file allocation table
- RDCF_FILE_NOT_FOUND file not found
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.4. rdcf_delete() - Delete a File, Volume Name or Subdirectory
- ----------------------------------------------------------------
-
- The following function call deletes a file, volume name or subdirectory:
-
- e = rdcf_delete(fcb, filespec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; file specification string, with
- terminating \0
-
- int e; 0 if file was successfully opened,
- or negative error code
-
- If RDCF_MULTIPLE_DRIVE is defined, the file specification for a volume name
- consists of a drive specification alone, e.g., "A:" for drive A:, "B:" for
- drive B:, etc. In other cases, the file specification for a volume name is
- the empty string ("").
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ----------------------------------------
- 0 successful operation
- RDCF_ACCESS_DENIED attempt to delete a read-only file or a
- subdirectory that is not empty
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_NOT_FOUND file, volume name or directory not found
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.5. rdcf_directory() - Create a New Subdirectory
- -------------------------------------------------
-
- The following function call creates a new subdirectory:
-
- e = rdcf_directory(fcb, filespec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; file specification string, with
- terminating \0
-
- int e; 0 if operation was successful,
- or negative error code
-
- The new directory, and its special subdirectories "." and "..", will bear the
- current date and time as determined by a call on rdcf_get_date_and_time().
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ----------------------------------------
- 0 successful operation
- RDCF_DIRECTORY_CONFLICT name conflicts with file or subdirectory
- RDCF_DIRECTORY_FULL insufficient directory or data space
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.6. rdcf_format() - Format a Disk
- ----------------------------------
-
- Formatting a disk usually involves two operations, both of which are performed
- by most DOS formatting utilities for diskettes.
-
- The first operation, called physical formatting, divides the tracks up into
- sectors and writes the necessary sector numbers into them. The sectors are
- filled with meaningless bytes. RDCF has no provision for physical formatting
- because the procedure is highly hardware-dependent.
-
- The second operation, called logical formatting, writes the required
- information into the bootstrap sector, the file allocation table, and the root
- directory. RDCF performs logical formatting with the following function call:
-
- e = rdcf_format(fcb, spec, format);
-
- struct rdcf *fcb; pointer to file control block
-
- char *spec; drive specification ("A:", "B:", etc.),
- omitted if RDCF_MULTIPLE_DRIVE is undefined
-
- struct rdcf_format *format; pointer to descriptor block for desired
- format
-
- int e; 0 if operation was successful,
- or negative error code
-
- The format parameter has any of four values, depending on the type of disk
- being formatted:
-
- value of format physical size density capacity
- ----------------- ------------- ------- --------
- &rdcf_format_360 5-1/4 inch double 360K
- &rdcf_format_720 3-1/2 inch double 720K
- &rdcf_format_1200 5-1/4 inch high 1.2M
- &rdcf_format_1440 3-1/2 inch high 1.44M
-
- Logical formatting deletes all files, subdirectories and the volume name. Some
- of this information can be reconstructed by rdcf_recover() or by special
- recovery programs if it has not been overwritten. However, all the information
- becomes inaccessible through normal DOS and RDCF calls. The disk also becomes
- unbootable and cannot be made bootable with the DOS SYS utility.
-
- This function is especially useful if the data storage device is not a
- DOS-compatible disk. You can use it to format a RAM disk, a portion of a hard
- disk, or even a file and use it as though it were a disk. The function
- (*drive_access)() usually needs to be modified, but no other changes are
- required.
-
- If you want to use a nonstandard format, you can make up your own format
- descriptor block. Here is what is in it:
-
- byte contents
- ---- ------------------------------------------------------
- 0 LS byte of number of bytes per sector
- 1 MS byte of number of bytes per sector
- 2 number of sectors per data cluster
- 3 1
- 4 0
- 5 number of file allocation tables
- 6 LS byte of number of root directory entries
- 7 MS byte of number of root directory entries
- 8 LS byte of total number of sectors
- 9 MS byte of total number of sectors
- 10 unused
- 11 LS byte of number of sectors per file allocation table
- 12 MS byte of number of sectors per file allocation table
- 13 LS byte of number of sectors per track
- 14 MS byte of number of sectors per track
- 15 LS byte of number of sides
- 16 MS byte of number of sides
- 17 unused
- 18 unused
-
- NOTICE that some two-byte parameters are not aligned on even boundaries.
-
- Of course, if you format a disk in a nonstandard manner, DOS may not be able to
- read it. There are a number of limitations on the parameters to guarantee a
- self-consistent format that RDCF can use:
-
- (1) None of the parameters can be zero (although the MS byte of a two-byte
- parameter can be zero).
-
- (2) The sector size must be a multiple of 32; but if RDCF_SECTOR_SIZE is
- defined, RDCF ignores this field.
-
- (3) The number of root directory entries must be a multiple of the number
- of entries in a sector. Each entry occupies 32 bytes, so if 512-byte
- sectors are used, the number of entries per sector is 16.
-
- (4) The disk contains the following areas, which must add up to the
- specified total number of sectors:
-
- (a) one bootstrap sector,
-
- (b) the specified number of file allocation tables, each containing
- the specified number of sectors,
-
- (c) the root directory, and
-
- (d) the data sectors.
-
- (5) The number of data sectors must be a multiple of the number of sectors
- per data cluster. Their quotient is the number of data clusters.
-
- (6) The number of data clusters must not exceed 65,517.
-
- (6) If the number of data clusters is 4077 or less, then each file
- allocation table must contain at least 3 bytes plus one and one-half
- bytes for each data cluster. Otherwise, each file allocation table
- must contain at least 4 bytes plus 2 bytes for each data cluster.
-
- Parameters described as "unused" are not used by RDCF, although they may have
- meanings on a DOS diskette. The rdcf_format() function makes only a
- perfunctory consistency check on the parameters.
-
- RDCF does not use the number of sectors per track or the number of sides, but
- the function (*drive_access)() may need them.
-
- Possible return values are as follows:
-
- return value meaning
- ------------------------ -----------------------------
- 0 successful operation
- RDCF_DISK_FORMAT_ERROR improper format control block
- RDCF_DRIVE_ERROR error in writing disk
- RDCF_INVALID_SPEC invalid drive specification
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.7. rdcf_free_space() - Get Disk Free Space
- ---------------------------------------------
-
- The following function call returns the number of bytes of free space on a
- disk:
-
- n = rdcf_free_space(fcb, char *spec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *spec; drive specification ("A:", "B:", etc.),
- omitted if RDCF_MULTIPLE_DRIVE is undefined
-
- long n; number of free bytes, or a
- negative error code
-
- If the operation is successful, the number of free bytes is also left in the
- member fcb->file.size.
-
- In the absence of drive errors, the number of free bytes returned by this
- function is the maximum number of bytes that can be added to an existing file
- that fills a whole number of data clusters. The number of additional bytes
- that can be written to existing files may be larger, because each file may
- have some empty space in its last cluster that is not counted as free by this
- function.
-
- The number of bytes that can be written to a newly created file is also the
- same as the value returned by this function, except in one peculiar case. If
- a new file is added to a subdirectory, it may be necessary to add a cluster to
- the subdirectory to accommodate the new file entry. This cluster is not
- available for file data.
-
- Possible error codes are as follows:
-
- return value meaning
- ---------------------- ---------------------------
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading disk
- RDCF_INVALID_SPEC invalid drive specification
-
-
- 8.8. rdcf_get_file_information() - Get a Directory Entry
- --------------------------------------------------------
-
- The following function reads a directory entry:
-
- e = rdcf_get_file_information(fcb, specs, index);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; directory specification string, with
- terminating \0
-
- unsigned index; index of desired entry (0 = first entry,
- 1 = second entry, etc.)
-
- int e; 0 if entry was successfully read,
- or negative error code
-
- If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
- root directory consists of a drive specification alone, such as "D:".
- Otherwise, the empty string ("") represents the root directory.
-
- If the operation is successful, useful information about the file, volume name
- or subdirectory will be found in the file information block fcb->file.
-
- If the return value is RDCF_FILE_NOT_FOUND, the entry represents an erased
- file, volume name or subdirectory. The first character in the name is invalid
- but other information is valid and reflects the status of the file, volume
- name or subdirectory before it was deleted.
-
- If the entry represents a volume name or subdirectory, the RDCF_VOLUME or
- RDCF_DIRECTORY bit will be set in the attribute byte.
-
- Entries 0 and 1 in a subdirectory represent the special directory entries named
- "." and "..". RDCF makes no use of these special entries, but it faithfully
- emulates this DOS feature.
-
- The value RDCF_DIRECTORY_FULL is returned if the index would put the entry
- beyond the end of the directory area, or if the entry lies inside this area but
- has never been used since the directory was created. In either case, the entry
- is invalid and there are no valid entries with any higher index value.
-
- Even if the entry is valid and represents a file, the file control block may
- not be used to read, write or otherwise manipulate the file until it is
- successfully opened by rdcf_open().
-
- If you call this function repeatedly to scan the directory, you should
- probably use some kind of caching. Otherwise, both the bootstrap block and the
- directory will be read from disk with each function call. Even without
- caching, this function produced acceptable results when used to display a
- directory listing of a floppy diskette, although the process was a little
- slower than most people would prefer.
-
- The companion function rdcf_next_file_information(), which is described below,
- can also be called to obtain the following entry without repeating the entire
- directory search.
-
- Possible return values are as follows:
-
- return value meaning
- ---------------------- ------------------------------
- 0 successful operation
- RDCF_DIRECTORY_FULL index is past end of directory
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading disk
- RDCF_FILE_NOT_FOUND entry represents deleted file
- RDCF_INVALID_SPEC invalid drive specification
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
-
-
- 8.9. rdcf_get_volume() - Get Volume Name
- ----------------------------------------
-
- The following function call scans the root directory for the volume name, if
- any:
-
- e = rdcf_get_volume(fcb, char *spec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *spec; drive specification ("A:", "B:", etc.),
- omitted if RDCF_MULTIPLE_DRIVE is undefined
-
- int e; 0 if volume name was successfully read,
- or negative error code
-
- If the operation is successful, information regarding the volume name is left
- in the file information block fcb->file.
-
- Possible return values are as follows:
-
- return value meaning
- ---------------------- ------------------------------
- 0 successful operation
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading disk
- RDCF_FILE_NOT_FOUND disk has no volume name
- RDCF_INVALID_SPEC invalid drive specification
-
-
- 8.10. rdcf_next_file_information() - Get Next Directory Entry
- -------------------------------------------------------------
-
- The following function reads the next directory entry after the one read by the
- most recent call on rdcf_get_file_information() or rdcf_next_file_information()
- using the same file control block:
-
- e = rdcf_next_file_information(fcb);
-
- struct rdcf *fcb; pointer to the same file control block used
- by a previous call on this function or
- rdcf_get_file_information()
-
- int e; 0 if entry was successfully read,
- or negative error code
-
- The file control block and scratch buffer must be the same ones used by the
- preceding call on rdcf_get_file_information() or this function, and the
- directory structure on the disk must not have changed. The preceding call must
- not have returned RDCF_DIRECTORY_FULL. This function uses information left in
- the file control block to find the next directory entry without rescanning the
- directory.
-
- If the operation is successful, useful information about the file, volume name
- or subdirectory will be found in the file information block fcb->file.
-
- If the return value is RDCF_FILE_NOT_FOUND, the entry represents an erased
- file, volume name or subdirectory. The first character in the name is invalid
- but other information is valid and reflects the status of the file, volume
- name or subdirectory before it was deleted.
-
- If the entry represents a volume name or subdirectory, the RDCF_VOLUME or
- RDCF_DIRECTORY bit will be set in the attribute byte.
-
- Entries 0 and 1 in a subdirectory represent the special directory entries named
- "." and "..". RDCF makes no use of these special entries, but it faithfully
- emulates this DOS quirk.
-
- The value RDCF_DIRECTORY_FULL is returned if the index would put the entry
- beyond the end of the directory area, or if the entry lies inside this area but
- has never been used since the directory was created. In either case, the entry
- is invalid and there are no valid entries with any higher index value.
-
- Even if the entry is valid and represents a file, the file control block may
- not be used to read, write or otherwise manipulate the file until it is
- successfully opened by rdcf_open().
-
- Possible return values are as follows:
-
- return value meaning
- ---------------------- ------------------------------
- 0 successful operation
- RDCF_DIRECTORY_FULL index is past end of directory
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading disk
- RDCF_FILE_NOT_FOUND entry represents deleted file
-
-
- 8.11. rdcf_match() - Match Name and Extension
- ---------------------------------------------
-
- The following function determines whether a DOS file name and extension match
- a DOS pattern, which may include the special characters ? and *:
-
- match = rdcf_match(name_extension, pattern);
-
- char *name_extension; DOS name and extension, with separating . and
- terminating \0
-
- char *pattern; DOS name and extension, with separating . and
- terminating \0, possibly including the special
- characters ? and *
-
- int match; true (nonzero) if the name and extension match
- the pattern; false (zero) otherwise
-
- The function follows all the usual DOS quirks. Small letters are converted to
- capital letters before comparison. The name is truncated to eight characters,
- and the extension is truncated to three characters.
-
- The function does not check the validity of the name and extension or the
- pattern.
-
-
- 8.12. rdcf_move() - Move a File or Subdirectory
- -----------------------------------------------
-
- The following function call moves a file or subdirectory from one directory to
- another ON THE SAME DRIVE:
-
- e = rdcf_move(fcb, old_filespec, new_filespec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *old_filespec; old file specification string, with
- terminating \0
-
- char *new_filespec; new file specification, with
- terminating \0
-
- int e; 0 if file was successfully opened,
- or negative error code
-
- The new file specification may not begin with a drive specification, even if
- RDCF_MULTIPLE_DRIVE is defined. However, it may, and often does, begin with a
- directory path.
-
- The file name and extension in the new file specification need not be the same
- as those in the old file specification. The file or subdirectory can be
- renamed as it is moved.
-
- The file or directory entry in the old position will be marked as deleted.
-
- You may use this function to move a subdirectory, but you must be careful not
- to corrupt the tree structure by moving a subdirectory into itself or one of
- its subdirectories. RDCF will not protect you from such folly.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ------------------------------------------
- 0 successful operation
- RDCF_DIRECTORY_FULL insufficient directory space for new entry
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_NOT_FOUND file not found
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_RENAMING_ERROR new file specification is already in use
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.13. rdcf_open() - Open a File
- -------------------------------
-
- The following function call opens a file:
-
- e = rdcf_open(fcb, filespec, mode);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; file specification string, with
- terminating \0
-
- unsigned mode; file mode (not used if RDCF is read-only)
-
- int e; 0 if file was successfully opened,
- or negative error code
-
- If the file is successfully opened, the file pointer is set to the beginning
- of the file and the file control block is initialized for use by other RDCF
- operations on the file. The file information block fcb->file then contains
- meaningful information about the file.
-
- The mode may be as follows:
-
- mode operation
- --------------- ------------------------------------------------
- RDCF_CREATE create file for writing, deleting the file if it
- already exists
- RDCF_READ open file for reading only
- RDCF_READ_WRITE open file for reading and writing
-
- In read-only file systems, RDCF_READ is the only mode permitted, so the mode
- parameter is absent.
-
- You may wish to open a file in the RDCF_READ mode merely to obtain information
- from its file control block. Then you can abandon or re-use the file control
- block; there is no need to close the file.
-
- You can emulate the full panoply of DOS open() modes by calling this function
- more than once.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ----------------------------------------------
- 0 successful operation
- RDCF_ACCESS_DENIED attempt to write a read-only file
- RDCF_DIRECTORY_CONFLICT file name conflicts with subdirectory
- RDCF_DIRECTORY_FULL insufficient directory space to create a file
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_NOT_FOUND file not found in RDCF_READ or RDCF_READ_WRITE
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_MODE_ERROR invalid mode
-
-
- 8.14. rdcf_read() - Read from a File
- ------------------------------------
-
- The following function call reads a block of bytes from an open file:
-
- n = rdcf_read(fcb, buffer, count);
-
- struct rdcf *fcb; pointer to open file control block
-
- void *buffer; memory buffer to receive data
-
- int count; number of bytes to be read
-
- int n; number of bytes actually read, or a negative
- error code
-
- The file control block must have been successfully opened in mode RDCF_READ or
- RDCF_READ_WRITE by rdcf_open().
-
- Reading starts at the current file pointer position. If the operation is
- successful, the file pointer is advanced to the byte immediately following the
- last byte read.
-
- The return value is the number of bytes actually read. If this nonnegative but
- less than the count, the end of the file was encountered.
-
- Errors are indicated by the following negative return values:
-
- return value meaning
- ---------------------- ------------------------------------------
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading disk
- RDCF_FILE_FORMAT_ERROR corrupt file allocation table
- RDCF_MODE_ERROR file mode not RDCF_READ or RDCF_READ_WRITE
-
-
- 8.15. rdcf_recover() - Recover Erased Data
- ------------------------------------------
-
- The following function call creates a new file and puts all unused data
- clusters into it:
-
- e = rdcf_recover(fcb, filespec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; file specification string, with
- terminating \0
-
- int e; 0 if file was successfully opened,
- or negative error code
-
- When a file is deleted by DOS or RDCF, the information contained in the file is
- not actually erased. The data clusters containing the information are merely
- marked as unused. Until these clusters are actually used for other files, the
- information is still there, and can be recovered and assembled into a single
- file by calling this function.
-
- The file specifications must be for a new file. If you try to use an existing
- file, this function will return the error code RDCF_ACCESS_DENIED.
-
- If you specify a file in a subdirectory, it will NOT be lengthened to
- accommodate the new file, as it would be when you call rdcf_open(). That would
- destroy information and partially defeat the purpose of this function. If
- there is no empty space in the subdirectory, this function will return the
- error code RDCF_DIRECTORY_FULL.
-
- If this function is successfully called, the new file will contain all the data
- in all unused clusters on the specified drive. Of course, the unused clusters
- will no longer be unused, and the drive will then be completely full. If you
- want to edit the information, you may have to copy the file to another drive
- that has room for the backup and scratch files that most text editors require.
- Some kind of editing is usually required because the new file will typically
- contain information from a number of old deleted files or subdirectories, and
- the information will be slightly mixed up if the old files were fragmented.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- -----------------------------------
- 0 successful operation
- RDCF_ACCESS_DENIED attempt to use an existing file
- RDCF_DIRECTORY_FULL insufficient directory space
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
- RDCF_INVALID_SPEC invalid drive or file specification
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.16. rdcf_rename() - Rename a File or Subdirectory
- ---------------------------------------------------
-
- The following function call changes the name and/or extension of a file or
- subdirectory:
-
- e = rdcf_rename(fcb, old_filespec, new_filespec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *old_filespec; old file specification string, with
- terminating \0
-
- char *new_filespec; new name and extension, with
- terminating \0
-
- int e; 0 if file was successfully opened,
- or negative error code
-
- The new file specification may not begin with a drive specification or
- directory path.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ----------------------------------------
- 0 successful operation
- RDCF_ACCESS_DENIED attempt to rename a hidden or system file
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_NOT_FOUND file not found
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_RENAMING_ERROR new file specification is already in use
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.17. rdcf_seek() - Move a File Pointer
- ---------------------------------------
-
- The following function call moves a file pointer:
-
- e = rdcf_seek(fcb, offset);
-
- struct rdcf *fcb; pointer to open file control block
-
- unsigned long offset; desired file pointer offset,
- relative to beginning of file
-
- int e; 0 for a successful operation,
- or a negative error code
-
- The file control block must have been successfully opened by rdcf_open() in any
- mode.
-
- If the operation is successful, the function returns zero. The next call on
- rdcf_read() or rcdf_write() will start at the specified position, relative to
- the beginning of the file.
-
- The file control block entry fcb->position or fcb->file.size can be used to
- convert an offset from the file pointer or end of file to an offset from the
- beginning of the file.
-
- A file cannot be lengthened by moving the file pointer past the end of the
- file. To lengthen a file, you must move the file pointer to the end of the
- file and then write enough data to it to make it the desired length.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------- -------------------------
- 0 successful operation
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading disk
- RDCF_SEEK_OUT_OF_RANGE offset exceeds file size
-
-
- 8.18. rdcf_set_file_information() - Set File Information
- --------------------------------------------------------
-
- The following function writes new information into a directory entry:
-
- e = rdcf_set_file_information(fcb, filespec, index, p);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; directory specification string, with
- terminating \0
-
- unsigned index; index of desired entry (0 = first entry,
- 1 = second entry, etc.)
-
- struct rdcf_file_information *p;
- pointer to block with new directory
- information
-
- int e; 0 if entry was successfully written,
- or negative error code
-
- If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
- root directory consists of a drive specification alone, such as "A:".
- Otherwise, the empty string ("") represents the root directory.
-
- This function takes a block of information, converts it to DOS directory
- format, and writes it into the specified directory entry. The block of
- information is usually supplied by rdcf_get_file_information. This function is
- used almost exclusively for special disk utilities.
-
- If p->spec[0] is zero, the entire entry will be cleared to zeros.
-
- This function will not lengthen a subdirectory if the index is past its current
- end.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ----------------------------------------
- 0 successful operation
- RDCF_DIRECTORY_FULL index is past end of directory
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
- RDCF_INVALID_SPEC invalid drive or file specification
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.19. rdcf_set_volume() - Write Volume Name
- -------------------------------------------
-
- The following function writes a new volume name:
-
- e = rdcf_set_volume(fcb, drive_name);
-
- struct rdcf *fcb; pointer to file control block
-
- char *drive_name; string of form "d:name" that specifies
- drive and name, with terminating \0
-
- int e; 0 if name was successfully written,
- or negative error code
-
- If RDCF_MULTIPLE_DRIVE is defined, the string drive_name begins with a drive
- specification (a drive letter, followed by a colon). Otherwise, it contains
- only the volume name. In any case, it is terminated by \0.
-
- If the volume name is less than 11 characters long, RDCF will pad it with
- blanks at the end before writing it to the disk.
-
- Notice that the volume name may contain small letters, which are NOT converted
- to capital letters by RDCF. Volume names in DOS are case-sensitive. RDCF will
- reject the volume name and return RDCF_INVALID_SPEC if the first character of
- the name is 0xE5, which indicates a deleted file or volume name.
-
- If there is already a volume name on the drive, it is replaced by the specified
- one.
-
- The new volume name will bear the current date and time as determined by a call
- on rdcf_get_date_and_time().
-
- return value meaning
- ---------------------- -----------------------------------
- 0 successful operation
- RDCF_DIRECTORY_FULL insufficient directory space
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading disk
- RDCF_INVALID_SPEC invalid drive specification or name
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.20. rdcf_sort_directory() - Sort a Directory
- ----------------------------------------------
-
- The following function call sorts a directory:
-
- e = rdcf_sort_directory(f, filespec, mode);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; directory specification string, with
- terminating \0
-
- int mode; code to indicate the kind of sort
-
- int e; 0 if directory was successfully sorted,
- or negative error code
-
- If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
- root directory consists of a drive specification alone, such as "A:".
- Otherwise, the empty string ("") represents the root directory.
-
- The sorting mode may be any ONE of the following:
-
- mode manner of sort
- ------------------- ---------------------------------------------
- RDCF_EXTENSION_NAME sort by extension, then among files that have
- the same extension, sort by name
- RDCF_NAME_EXTENSION sort by name, then among files that have
- the same name, sort by extension
- RDCF_DATE_TIME sort by date and time (earlier files first)
- RDCF_SIZE sort by size (smallest files first)
-
- The modifier RDCF_REVERSE may be added to any of these modes to sort in the
- opposite order. For example, RDCF_SIZE+RDCF_REVERSE sorts the files by size,
- but it puts the largest files first.
-
- Actually, before the function sorts the directory entries, it first divides
- them into five groups and arranges them in the following order:
-
- (1) The two system files at the beginning of the root directory and the
- two special files "." and ".." at the beginning of a subdirectory are
- always left where they are.
-
- (2) The volume label, if any, is put next.
-
- (3) The subdirectory entries, if any, are sorted and put next.
-
- (4) The file entries are sorted and put next.
-
- (5) The entries for deleted files, volume labels and subdirectories, if
- any, are sorted and put last.
-
- Within each category, if two entries are identical according to the sorting
- criterion, their relative position is left unchanged.
-
- Some kind of caching is strongly recommended when using this function. The
- sorting algorithm is rather primitive one called a "bubble sort", so it may
- take a noticeable amount of time to sort a long directory, even with caching.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ----------------------------------------
- 0 successful operation
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
- RDCF_INVALID_SPEC invalid drive or file specification
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.21. rdcf_undelete() - Restore a Deleted File
- ----------------------------------------------
-
- When you delete a file, with either DOS or RDCF, the information in the file is
- not erased, although it may become rather difficult to find.
-
- The following function call restores the original contents of a deleted file,
- to the extent possible:
-
- e = rdcf_undelete(fcb, filespec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *filespec; file specification string, with
- terminating \0
-
- int e; 0 if file was even partially recovered,
- or negative error code
-
- The function will attempt to restore as much of the file as possible. If only
- part of the file can be restored, the value in fcb->position will indicate how
- much of the file was NOT restored. If the entire file was restored, this entry
- will be zero. If nothing can be restored because the first data cluster of the
- file is in use by another file, the function will return
- RDCF_UNRECOVERABLE_FILE.
-
- Even an apparently successful restoration may not restore the original file
- contents. For example, if another file was written over the original file
- contents and then deleted, RDCF may have no way of knowing that the file
- contents have changed.
-
- Complete restoration of a file can be assured if the original file was
- unfragmented before it was deleted and nothing has been written to the disk
- after it was deleted.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ---------------------------------------
- 0 fully or partially successful operation
- RDCF_DIRECTORY_FULL index is past end of directory
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_NOT_FOUND entry did not represent a deleted file
- RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
- RDCF_INVALID_SPEC invalid drive or file specification
- RDCF_UNRECOVERABLE_FILE none of the file can be restored
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.22. rdcf_wipe_disk() - Wipe Out Erased Data
- ---------------------------------------------
-
- The following function call writes nonsense over all unused clusters of the
- specified drive:
-
- e = rdcf_wipe_disk(fcb, spec);
-
- struct rdcf *fcb; pointer to file control block
-
- char *spec; drive specification ("A:", "B:", etc.),
- omitted if RDCF_MULTIPLE_DRIVE is undefined
-
- int e; 0 if operation was successful,
- or negative error code
-
- When a file is deleted by DOS or RDCF, the information contained in the file is
- not actually erased. The data clusters containing the information are merely
- marked as unused. Until these clusters are actually used for other files, the
- information is still there, and can often be recovered by calling
- rdcf_undelete() or rdcf_recover() or by using a file recovery utility.
-
- For security reasons, you may want to make sure your erased files are really
- erased. This function does that by writing nonsense into every cluster marked
- as unused.
-
- The information is not completely destroyed. It may be possible to read some of
- it by subjecting the disk to a special analysis in a laboratory, but it cannot
- be read by an ordinary file recovery utility.
-
- Even erasing every unused cluster won't necessarily remove all the information
- from erased files. There may be unused sectors at the ends of files that are
- not erased. The last cluster of such a file is not marked as unused, because
- part of it is being used. But the part that is not being used may contain
- information from an older file that did use the entire cluster.
-
- Possible return values are as follows:
-
- return value meaning
- ----------------------- ------------------------------------------
- 0 fully or partially successful operation
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_INVALID_SPEC invalid drive specification
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- 8.23. rdcf_write() - Write to a File
- ------------------------------------
-
- The following function call writes a block of bytes to an open file:
-
- n = rdcf_write(fcb, buffer, count);
-
- struct rdcf *fcb; pointer to open file control block
-
- void *buffer; memory buffer to supply data
-
- int count; number of bytes to be written
-
- int n; number of bytes actually written, or a negative
- error code
-
- The file control block must have been successfully opened in mode RDCF_CREATE
- or RDCF_READ_WRITE by rdcf_open().
-
- Writing starts at the current file pointer position. If the operation is
- successful, the file pointer is advanced to the byte immediately following the
- last byte written.
-
- If necessary, the file is lengthened to accommodate the bytes being written.
-
- The return value is the number of bytes actually written. If this is
- nonnegative but less than the count, there was insufficient disk space to write
- all the data.
-
- Other errors are indicated by the following negative return values:
-
- return value meaning
- --------------------- --------------------------------------------
- RDCF_DISK_FORMAT_ERROR disk improperly formatted
- RDCF_DRIVE_ERROR error in reading or writing disk
- RDCF_FILE_FORMAT_ERROR corrupt file allocation table
- RDCF_MODE_ERROR file mode not RDCF_CREATE or RDCF_READ_WRITE
-
- This function also sets an internal flag to indicate that the file has been
- written, which causes RDCF to update the directory when the file is later
- closed. If the count is zero, setting the flag is all it does.
-
- If RDCF is compiled as a read-only file system, this function is not defined.
-
-
- ----------------end-of-author's-documentation---------------
-
- Software Library Information:
-
- This disk copy provided as a service of
-
- Public (software) Library
-
- We are not the authors of this program, nor are we associated
- with the author in any way other than as a distributor of the
- program in accordance with the author's terms of distribution.
-
- Please direct shareware payments and specific questions about
- this program to the author of the program, whose name appears
- elsewhere in this documentation. If you have trouble getting
- in touch with the author, we will do whatever we can to help
- you with your questions. All programs have been tested and do
- run. To report problems, please use the form that is in the
- file PROBLEM.DOC on many of our disks or in other written for-
- mat with screen printouts, if possible. PsL cannot debug pro-
- programs over the telephone, though we can answer questions.
-
- Disks in the PsL are updated monthly, so if you did not get
- this disk directly from the PsL, you should be aware that the
- files in this set may no longer be the current versions. Also,
- if you got this disk from another vendor and are having prob-
- lems, be aware that some files may have become corrupted or
- lost by that vendor. Get a current, working disk from PsL.
-
- For a copy of the latest monthly software library newsletter
- and a list of the 4,000+ disks in the library, call or write
-
- Public (software) Library
- P.O.Box 35705
- Houston, TX 77235-5705
-
- Orders only:
- 1-800-2424-PSL
- MC/Visa/AmEx/Discover
-
- Outside of U.S. or in Texas
- or for general information,
- Call 1-713-524-6394